package com.xuecheng.media.jobhandler;

import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.xuecheng.base.utils.FFMpegUtils;
import com.xuecheng.content.model.dto.MediaFilesDto;
import com.xuecheng.content.model.dto.MediaFilesTaskDto;
import com.xuecheng.content.model.dto.MultPartFileInfoInit;
import com.xuecheng.content.model.po.MediaFiles;
import com.xuecheng.content.model.po.MediaProcess;
import com.xuecheng.content.model.po.MediaProcessHistory;
import com.xuecheng.media.client.TeachplanMediaClient;
import com.xuecheng.media.conver.MediaFilesConver;
import com.xuecheng.media.conver.VideoTaskCover;
import com.xuecheng.media.mapper.MediaProcessHistoryMapper;
import com.xuecheng.media.service.MediaFilesService;
import com.xuecheng.media.service.MediaProcessHistoryService;
import com.xuecheng.media.service.MediaProcessService;
import com.xuecheng.media.service.MinIoService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.swing.plaf.OptionPaneUI;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.alibaba.fastjson.JSONPatch.OperationType.add;

@Slf4j
@Component
public class VideoTask {

    @Autowired
    private MediaFilesService mediaFilesService;

    @Autowired
    private MediaProcessService mediaProcessService;

    @Autowired
    private MediaProcessHistoryService mediaProcessHistoryService;
    @Autowired
    private TeachplanMediaClient teachplanMediaClient;

    @Autowired
    private MinIoService minIoService;
    private static final Logger logger = LoggerFactory.getLogger(VideoTask.class);


    @XxlJob("testJobHandler")
    public void demoJobHandler() throws Exception {
        XxlJobHelper.log("XXL-JOB, Hello World.");
        System.out.println("启动成功");

        for (int i = 0; i < 5; i++) {
            XxlJobHelper.log("beat at:" + i);
            TimeUnit.SECONDS.sleep(2);
        }
        // default success
    }


//    @XxlJob("convertedMp4Video")
    @Transactional(rollbackFor = Exception.class)
    public void convertedToMp4() {
        // 1. 查询待转换文件（保持原始格式）
        List<MediaFilesTaskDto> mediaFilesTaskDtos = mediaFilesService.selectWaitConvertedVideos();//待处理任务
        if (CollectionUtils.isEmpty(mediaFilesTaskDtos)) return;

        // 2. 将待转换文件复制到临时任务表
        List<MediaProcess> newTasks = mediaFilesTaskDtos.stream()
                .map(mediaFile -> {
                    // 创建处理任务时设置初始状态
                    MediaProcess task = new VideoTaskCover().mediaFilesConverToMediaProcess(mediaFile);
                    task.setStatus("1"); // 待处理
                    return task;
                })
                .collect(Collectors.toList());
        mediaProcessService.batchInsertOrUpdate(newTasks);

        // 3. 处理每个任务
        for (MediaProcess task : newTasks) {
            try {
                processTask(task);
            } catch (Exception e) {
                log.error("捕获到 processTask 异常", e); // 添加这行日志
                handleTaskFailure(task, e);
            }
        }
    }

    // 封装任务处理逻辑
    private void processTask(MediaProcess task) throws Exception {
        // 1. 下载原始文件
        String tempFilePath = minIoService.downloadToTemp(task.getUrl());
        File originalFile = new File(tempFilePath);

        // 2. 转换文件
        String convertedPath = FFMpegUtils.convertToMp4(tempFilePath);
        File convertedFile = new File(convertedPath);

        // 3. 上传转换后的文件到MinIO（新路径）
        MultPartFileInfoInit fileInfo = minIoService.splitFileToChunks(convertedFile);
        fileInfo.setFileName(task.getFilename());
        minIoService.mergeChunks(fileInfo);

        // 4. 创建新文件记录（暂不插入）
        MediaFiles convertedFileRecord = mediaFilesService.convertedToMediaFile(fileInfo);

        // 5. 记录转换历史
        MediaProcessHistory historyRecord = new MediaProcessHistory();
        BeanUtils.copyProperties(task, historyRecord);
        historyRecord.setStatus("2");
        historyRecord.setFinishDate(LocalDateTime.now());
        mediaProcessHistoryService.insert(historyRecord);

        // 6. 更新关联数据
        updateReferences(task, convertedFileRecord);

        // 7. 删除原始文件和记录（最终操作）
        mediaFilesService.deleteMinioById(task.getFileId());
        mediaProcessService.deleteByFileId(task.getFileId());
        // 8. 清理临时文件
        Files.deleteIfExists(originalFile.toPath());
        Files.deleteIfExists(convertedFile.toPath());
    }

    // 更新关联引用
    private void updateReferences(MediaProcess task, MediaFiles newFile) {
        // 1. 插入新文件记录
        mediaFilesService.insert(newFile);

        // 2. 更新教学计划中的关联
        Map<String, MediaFilesDto> updateMap = new HashMap<>();
        MediaFilesDto dto = new MediaFilesDto();
        BeanUtils.copyProperties(newFile, dto);
        updateMap.put(task.getFileId(), dto);

        // 3. 远程调用
        teachplanMediaClient.updateFileInfo(updateMap);

        // 4. 更新任务状态
        task.setStatus("2");
        task.setFinishDate(LocalDateTime.now());
        mediaProcessService.updateById(task);
    }


    // 错误处理
    private void handleTaskFailure(MediaProcess task, Exception e) {
        log.error("视频处理失败 | 文件ID: {} | 错误: {}", task.getFileId(), e.getMessage(), e);
        String fileId = task.getFileId();
        if (fileId != null) {
            // 查询历史失败次数（注意：这里统计的是历史记录总数）
            MediaProcessHistory mediaProcessHistory = mediaProcessHistoryService.selectByFileId(fileId);

            int newFailCount = 0;       //初始化失败记录
            if(mediaProcessHistory != null){
                newFailCount =mediaProcessHistory.getFailCount()+1;  // 本次失败后新的总失败次数
            }

            // 统一设置任务状态信息（避免多处重复设置）
            task.setFailCount(newFailCount);
            task.setStatus("3");
            task.setErrormsg(e.getMessage().length() > 500 ? e.getMessage().substring(0, 500) : e.getMessage());
            task.setFinishDate(LocalDateTime.now());

            // 创建历史记录对象（统一处理）
            MediaProcessHistory mediaProcessHistoryInsert = new MediaProcessHistory();
            BeanUtils.copyProperties(task, mediaProcessHistoryInsert);
            mediaProcessService.deleteByFileId(task.getFileId());
            // 处理不同的失败场景
            if (newFailCount == 0) {
                // 首次失败：插入新记录
                mediaProcessHistoryService.insert(mediaProcessHistoryInsert);
            } else {
                // 非首次失败：更新现有记录
                mediaProcessHistoryService.updateById(mediaProcessHistoryInsert);
            }

            // 失败超过3次时需更新媒体文件状态
            if (newFailCount > 3) {
                MediaFiles mediaFilesInsert = new MediaFiles();
                mediaFilesInsert.setId(Long.valueOf(task.getFileId()));
                mediaFilesInsert.setFileId(task.getFileId());
                mediaFilesInsert.setAuditStatus("002002");      //跟该文件为待审核
                mediaFilesService.updateNotEmpty(mediaFilesInsert);
            }
        }
    }



}
